package org.thanos.simulator.page.point;

import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.RandomUtil;
import org.thanos.bacnet.obj.BACnetObject;
import org.thanos.bacnet.type.enumerated.ObjectType;
import org.thanos.simulator.api.BACnetIpClient;
import org.thanos.simulator.page.IndexPage;
import org.thanos.simulator.util.PropertyUtil;

import javax.swing.*;
import javax.swing.text.NumberFormatter;
import java.awt.*;
import java.math.BigDecimal;
import java.text.NumberFormat;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

public class ObjectConfigPage {

    private final JComboBox<String> objectType;
    private final JTextField count;
    private final JComboBox<String> isRandom;
    private JTextField value;
    private JComboBox<String> binaryValue;
    private GridBagConstraints valuePosition;

    public ObjectConfigPage(IndexPage indexPage) {
        // 创建 JFrame
        JFrame frame = new JFrame("对象配置");
        frame.setLocation(GraphicsEnvironment.getLocalGraphicsEnvironment().getCenterPoint());
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.setLayout(new GridBagLayout()); // 使用 GridBagLayout

        // 创建 GridBagConstraints
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.insets = new Insets(5, 5, 5, 5); // 设置组件之间的间距

        // 创建下拉框
        List<String> options = PropertyUtil.supportedObjectType().stream().map(ObjectType::toString).collect(Collectors.toList());
        objectType = new JComboBox<>(options.toArray(new String[]{}));
        objectType.setPreferredSize(new Dimension(150, 30)); // 设置尺寸为 150x30 像素
        frame.add(new JLabel("选择对象类型:"), gbc); // 添加标签
        gbc.gridx++;
        frame.add(objectType, gbc);
        objectType.addItemListener(e -> {
            String isBinaryValue = e.getItem().toString();
            List<String> binaries = Stream.of(ObjectType.binaryInput, ObjectType.binaryOutput, ObjectType.binaryValue).map(ObjectType::toString).collect(Collectors.toList());
            if (binaries.contains(isBinaryValue)) {
                if (Objects.nonNull(value)) {
                    frame.remove(value);
                    frame.repaint();
                    frame.revalidate();
                    binaryValue = new JComboBox<>(new String[]{"true", "false"});
                    binaryValue.setPreferredSize(new Dimension(150, 30)); // 设置尺寸为 150x30 像素
                    frame.add(binaryValue, valuePosition);
                    frame.repaint();
                    frame.revalidate();
                    value = null;
                }
            } else {
                if (Objects.nonNull(binaryValue)) {
                    frame.remove(binaryValue);
                    frame.repaint();
                    frame.revalidate();
                    value = new JFormattedTextField(this.buildNumberFormatter());
                    value.setPreferredSize(new Dimension(150, 30)); // 设置尺寸为 150x30 像素
                    frame.add(value, valuePosition);
                    frame.repaint();
                    frame.revalidate();
                    binaryValue = null;
                }
            }
        });

        gbc.gridx = 0;
        gbc.gridy++;
        frame.add(new JLabel("数量:"), gbc); // 添加标签
        gbc.gridx++;
        count = new JFormattedTextField(this.buildNumberFormatter());
        count.setPreferredSize(new Dimension(150, 30)); // 设置尺寸为 150x30 像素
        frame.add(count, gbc);

        gbc.gridx = 0;
        gbc.gridy++;
        frame.add(new JLabel("初始值:"), gbc); // 添加标签
        gbc.gridx++;
        value = new JFormattedTextField(this.buildNumberFormatter());
        value.setPreferredSize(new Dimension(150, 30)); // 设置尺寸为 150x30 像素
        valuePosition = new GridBagConstraints(gbc.gridx, gbc.gridy, gbc.gridwidth, gbc.gridheight, gbc.weightx, gbc.weighty, gbc.anchor, gbc.fill, gbc.insets, gbc.ipadx, gbc.ipady);
        frame.add(value, valuePosition);

        gbc.gridx = 0;
        gbc.gridy++;
        frame.add(new JLabel("是否随机变化:"), gbc); // 添加标签
        gbc.gridx++;
        isRandom = new JComboBox<>(new String[]{"true", "false"});
        isRandom.setPreferredSize(new Dimension(150, 30)); // 设置尺寸为 150x30 像素
        frame.add(isRandom, gbc);

        // 创建确认按钮
        gbc.gridx = 0;
        gbc.gridy++;
        gbc.gridwidth = 2;
        gbc.anchor = GridBagConstraints.CENTER;
        JButton button = new JButton("确认");
        button.addActionListener(e -> {
            try {
                String type = Objects.requireNonNull(objectType.getSelectedItem()).toString();
                int countValue = NumberFormat.getIntegerInstance().parse(count.getText()).intValue();
                ObjectType bACnetObjectType = ObjectType.forName(type);
                long start = BACnetIpClient.getNextInstanceNumber(bACnetObjectType);
                boolean isRandomValue = Boolean.parseBoolean(Objects.requireNonNull(isRandom.getSelectedItem()).toString());
                BACnetObject object = null;
                if (PropertyUtil.analogTypes().stream().map(ObjectType::toString).collect(Collectors.toList()).contains(type)) {
                    double presentValue = CharSequenceUtil.isNotBlank(value.getText()) ? NumberFormat.getNumberInstance().parse(value.getText()).doubleValue() : 0.0d;
                    for (int i = (int) start; i < start + countValue; i++) {
                        object = BACnetIpClient.createAnalogObject(bACnetObjectType, bACnetObjectType.toString().concat(CharSequenceUtil.SPACE).concat(String.valueOf(i)), BigDecimal.valueOf(presentValue), null, false);
                        if (isRandomValue && Objects.nonNull(object)) {
                            BACnetIpClient.addRandomObject(object);
                        }
                    }
                } else if (PropertyUtil.binaryTypes().stream().map(ObjectType::toString).collect(Collectors.toList()).contains(type)) {
                    Boolean presentValue = Objects.nonNull(binaryValue.getSelectedItem()) && Boolean.parseBoolean(binaryValue.getSelectedItem().toString());
                    for (int i = (int) start; i < start + countValue; i++) {
                        object = BACnetIpClient.createBinaryObject(bACnetObjectType, bACnetObjectType.toString().concat(CharSequenceUtil.SPACE).concat(String.valueOf(i)), presentValue, false);
                        if (isRandomValue && Objects.nonNull(object)) {
                            BACnetIpClient.addRandomObject(object);
                        }
                    }
                } else if (PropertyUtil.multiStateTypes().stream().map(ObjectType::toString).collect(Collectors.toList()).contains(type)) {
                    int presentValue = CharSequenceUtil.isNotBlank(value.getText()) ? NumberFormat.getIntegerInstance().parse(value.getText()).intValue() : 0;
                    for (int i = (int) start; i < start + countValue; i++) {
                        List<String> stateTexts = IntStream.range(0, presentValue).mapToObj(RandomUtil::randomString).collect(Collectors.toList());
                        object = BACnetIpClient.createMultiStateObject(bACnetObjectType, bACnetObjectType.toString().concat(CharSequenceUtil.SPACE).concat(String.valueOf(i)), stateTexts, presentValue, false);
                        if (isRandomValue && Objects.nonNull(object)) {
                            BACnetIpClient.addRandomObject(object);
                        }
                    }
                }
                indexPage.reloadTree();
                frame.dispose();
            } catch (Exception ex) {
                throw new RuntimeException(ex);
            }
        });
        frame.add(button, gbc);
        frame.pack(); // 自适应大小
        frame.setVisible(true);
    }

    private NumberFormatter buildNumberFormatter() {
        // 创建数字输入框
        NumberFormat format = NumberFormat.getInstance();
        NumberFormatter formatter = new NumberFormatter(format);
        formatter.setValueClass(Integer.class);
        formatter.setMinimum(0);
        formatter.setMaximum(Integer.MAX_VALUE);
        return formatter;
    }
}
